import { Component, ElementRef, Renderer2, ViewChild, ViewChildren } from '@angular/core';
import { DesktopItemDto } from '../desktop-item-cmp/desktop-item-dto';
import { file, folder, QueryDto } from 'ispace.core.main';
import { fileInfoBaseDto } from 'ispace.core.main/dist/dto/fileInfoBaseDto';
import { DesktopItemCmpComponent } from '../desktop-item-cmp/desktop-item-cmp.component';
import { CommonModule } from '@angular/common';
import { CdkDrag, CdkDragEnd, CdkDragMove, CdkDragStart } from '@angular/cdk/drag-drop';
import { isRangesIntersection } from '../../common/utils/numberUtil';
import { WindowContainerCmpComponent } from "../window-container-cmp/window-container-cmp.component"; 
import { CdkMenuModule } from '@angular/cdk/menu';
import { DriveEnginService } from '../../service/drive-engin.service';
import { DriverOperationDto } from 'ispace_de';
import { SelectionBoxCmpComponent } from "../selection-box-cmp/selection-box-cmp.component";
import { SelectableDirective } from '../selection-box-cmp/selectable.directive';
import { DesktopService } from '../../service/desktop.service';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';

@Component({
  selector: 'app-desktop-cmp',
  standalone: true,
  imports: [DesktopItemCmpComponent,SelectableDirective,
    CommonModule,
    CdkDrag,
    WindowContainerCmpComponent,
    CdkMenuModule, SelectionBoxCmpComponent,
    MatIconModule,
    MatMenuModule
  ],
  templateUrl: './desktop-cmp.component.html',
  styleUrl: './desktop-cmp.component.sass'
})
export class DesktopCmpComponent {

  
dragPostion: { x: number, y: number ,dx: number,dy:number} = { x: 0, y: 0 ,dx:0,dy:0};
onDragStarted($event: CdkDragStart<any>,item: DesktopItemDto) {
  this.dragPostion ={  x: item.position.x, y: item.position.y,dx:0,dy:0}; 
}
 

onDragMoved($event: CdkDragMove<any>,item: DesktopItemDto) {
  if(this.desktopSvc.selectedItemList.value.length <=1) {  
    return;
  } 

  if(!this.desktopSvc.selectedItemList.value.some(s => s.id == item.id)) {
    return;
  } 
 
  this.dragPostion.dx = $event.source.getFreeDragPosition().x - this.dragPostion.x;
  this.dragPostion.dy = $event.source.getFreeDragPosition().y - this.dragPostion.y;
 

  // 多个选中项，则选中项的位置在原位置，同等平移
  this.desktopSvc.selectedItemList.value.forEach(s => {
    if(s.id == item.id) {
      return;
    } 
        s.position = {
          x: s.position.x + this.dragPostion.dx,
          y: s.position.y +  this.dragPostion.dy
        };  
    });

  // 更新位置
  this.dragPostion.x = $event.source.getFreeDragPosition().x;
  this.dragPostion.y = $event.source.getFreeDragPosition().y; 
}
   

  constructor(private driveEngine: DriveEnginService,private renderer: Renderer2,private desktopSvc:DesktopService) {
     // 3. 添加全局点击监听
    this.globalClickListener = this.renderer.listen(
      'document',
      'mouseup',
      (event: MouseEvent) => { 
        if(this.desktopSvc.selectedItemList.value.length == 0) {
          return;
        }
        if(event.button != 0){
          return;
        }
 
        // 如果点击的不是当前组件的子元素，则清空选中项
        if (this.childElementRef.some(s=>s.nativeElement.contains(event.target as Node))) {
          return;
        }
        // 排除菜单点击
        if (event.target instanceof HTMLElement && event.target.classList.contains('cdk-menu-item')) {
          return;
        }
         this.desktopSvc.selectedItemList.next([]);
      }
    );

    this.desktopSvc.refreshEvent.subscribe(s=>{
      this.load();
    })
 
  }
  
  ngOnDestroy() {
    // 清除全局点击监听
    if (this.globalClickListener) {
      this.globalClickListener();
    }
  }
 
@ViewChildren('desktop_item', { read: ElementRef<HTMLElement> }) 
childElementRef!: ElementRef<HTMLElement>[];

private globalClickListener!: () => void;  

clickItem(event: MouseEvent,item:DesktopItemDto) {  
 
  if(event.button != 0){
    return;
  }

  const isCtrlPressed = event.ctrlKey || event.metaKey; // 检查是否按下了 Ctrl 键

  if (isCtrlPressed) {
    if(!this.desktopSvc.selectedItemList.value.includes(item)) {
    this.desktopSvc.selectedItemList.value.push(item);
    return;
    }
  }

  const isShiftPressed = event.shiftKey; // 检查是否按下了 Shift 键
  if (isShiftPressed) {

    if(this.desktopSvc.selectedItemList.value.length == 0) {
      this.desktopSvc.selectedItemList.value.push(item);
      return;
    }

    // 根据 position 对 desktopItems 进行排序
    let sortedItems = this.desktopItems.sort((a, b) => {
      return a.position.y - b.position.y || a.position.x - b.position.x;
    });

    let lastItem = this.desktopSvc.selectedItemList.value[this.desktopSvc.selectedItemList.value.length - 1];

    // 找到选中项和点击项在排序后的数组中的位置
    let startIndex = sortedItems.findIndex(s => s.id == lastItem.id);
    let endIndex = sortedItems.findIndex(s => s.id == item.id);

    // 确保 startIndex 小于 endIndex
    if (startIndex > endIndex) {
      let temp = startIndex;
      startIndex = endIndex;
      endIndex = temp;
    }

    // 选择 startIndex 和 endIndex 之间的所有项
    for (let i = startIndex; i <= endIndex; i++) {
      if (!this.desktopSvc.selectedItemList.value.includes(sortedItems[i])) {
        this.desktopSvc.selectedItemList.value.push(sortedItems[i]);
      }
    }
    return;
    }

  
  this.desktopSvc.selectedItemList.next([]);
  this.desktopSvc.selectedItemList.value.push(item);
}

itemSelected(item: DesktopItemDto) {
 return this.desktopSvc.selectedItemList.value.some(s => s.id == item.id);  
}

handleItemsSelected(event: DesktopItemDto[]) {
  this.desktopSvc.selectedItemList.next([]);
  event.forEach(s => {
    this.desktopSvc.selectedItemList.value.push(s);
  });

}
 
ext_operations: DriverOperationDto[] = [];
init_sourceManagerOpen() { 
  this.ext_operations=  this.driveEngine.getOperations(this.basePath,true); 

  let op =  this.ext_operations.find(s=>s.driverId==1 && s.id==1);
      if(!op)
        {
          console.error("not found");
          return;
        }
  this.iconUrl= this.driveEngine.driveEngine.drivers.value.find(s=>s.id==op!.driverId)?.fileIconUrl??"";
     


}

ext_operation_execute(operation: DriverOperationDto) {
  this.driveEngine.execute(operation.driverId,operation.id,this.basePath,'folder',{ name: this.basePath, type: "folder",iconUrl:this.iconUrl });
}

removeItem(data: DesktopItemDto|DesktopItemDto[]) { 
  if(Array.isArray(data)) {
    data.forEach(s => {
      this.removeItem(s);
    })
    return;
  }
  if(data.type == "folder") {
    folder.remove(this.basePath, data.name).subscribe(s => {
      this.load();
    }, e => {
      console.error(e);
    })
  }
  else {
    file.remove(this.basePath, data.name).subscribe(s => {
      this.load();
    }, e => {
      console.error(e);
    })
  }
} 
 
  basePath = "Desktop"
  positionPath = "/.ispace/desktopitem_position.json"
  iconUrl = "";

  desktopItems: DesktopItemDto[] = [];

  positions: { [key: string]: { x: number, y: number } } = {};

  @ViewChild("body", { static: false }) body!: ElementRef;

 

  ngOnInit() {
    this.init();
  }

  init() {
    this.load();
    this.load_templates();
    this.init_sourceManagerOpen();
  }

  update_position() {

    let ps: { [key: string]: { x: number, y: number } } = {};
    this.desktopItems.forEach(s => {
      ps[s.id] = s.position;
    });
    if (Object.keys(ps).length <= 0) {
      return;
    }

    let content = JSON.stringify(ps);

    file.write(this.basePath + this.positionPath, content)
      .subscribe(
        s => {
          //console.log(s)
        }, e => { 
          console.error(e)
        });
  }

  load_retryTime = 0;
  load() {
    // 加载桌面文件、文件夹数据；
    this.load_children().then((s) => { 
      if (s) {
        // 加载桌面项位置信息
        return this.load_position();
      }
      return Promise.resolve(false);
    }).then((s) => {
      if (s) {
        // 构建桌面项，生成桌面项列表
        return this.rendering();
      }else{
        this.load_retryTime++;
        let time = 1000*(this.load_retryTime>5?5:this.load_retryTime);
        setInterval(() => { this.load(); }, time); 
      }
    });
  }

  isCanPasteFlag = false;

  async contextMenuOpened(event: any) {
    this.isCanPasteFlag = await this.isCanPaste();
  }

  isCanPaste = ()=>{ 
    return navigator.clipboard.readText().then(s => { 
    if(s?.length <=0) {
      return false;
    }
    if(s.startsWith("$ispace copy") == false && s.startsWith("$ispace shear") == false) {
      return false; 
    } 
      return true;
    }).catch(e=>{ 
      console.error(e);
      return false;
    });
  }
  
  paste() { 
    navigator.clipboard.readText().then(s => { 
      let datas = s.replace("\r\n","\n").split("\n");
      datas.forEach(s => {
      let info = s.replace('\r','').split(" "); 
      let path = info[3]
      let fileType = info[4];
      let type = info[1];
      let nameS = path.split("/");
      let name = nameS[nameS.length - 1];
      let data = { type: fileType as 'file'|'folder', path: path,name: name};
      this.paste_one(data as DesktopItemDto,type);
      }) 
    }).catch(e=>{ 
      console.error(e);
    });
  }

  paste_one(desktopItemDto: DesktopItemDto,type:string) {
      if (desktopItemDto.type == "file") {
        if (type == "copy") {

          file.copy(desktopItemDto.path, this.basePath +"/" +desktopItemDto.name).subscribe(s => {
            this.load();
          }, e => {
          console.error(e);
          });
        }
        if (type == "shear") {
          file.move(desktopItemDto.path, this.basePath +"/" + desktopItemDto.name).subscribe(s => {
            this.load();
          }, e => {
            console.error(e);
          }
          ) 
        }
      }

      if (desktopItemDto.type  == "folder") {
        if (type == "copy") {
          folder.copy(desktopItemDto.path, this.basePath +"/" + desktopItemDto.name).subscribe(s => {
            this.load();
          }, e => { 
            console.error(e);
          });
        }
        if (type == "shear") {
          folder.move(desktopItemDto.path, this.basePath +"/" + desktopItemDto.name).subscribe(s => {
            this.load();
          }, e => { 
            console.error(e);
          }
          ) 
        }
      }
  }

  load_children(): Promise<boolean> {
    // 加载桌面文件、文件夹数据
    return new Promise<boolean>((resolve) => {
      let query = new QueryDto();
      query.path = this.basePath;
      folder.children(query)
        .subscribe(
          (s) => {

            // rm item :
            let rmIds: string[] = [];
            this.desktopItems.forEach((item) => {
              if(s.findIndex((s) => s.id == item.id) == -1){
                 rmIds.push(item.id);
              }
            })

            rmIds.forEach((id) => {
              this.desktopItems.splice(this.desktopItems.findIndex((s) => s.id == id), 1);
            })
 
            // add item : 
            s.forEach((info) => { 
              if(this.desktopItems.findIndex((s) => s.id == info.id)==-1){
              this.desktopItems.push(this.convertInfo(info));  
              } 
            })
            resolve(true);
          },
          (e) => {
            console.log(e);
            resolve(false);
          }
        )
    })

  }

  load_position(): Promise<boolean> {
    // 加载桌面项位置信息
    return new Promise<boolean>((resolve) => {
      // 获取 basePath + .position 文件,内容信息
      file.content(this.basePath + this.positionPath)
        .subscribe((s) => {
          // 保存到当前变量
          if (s?.length > 0) {
            try{
            this.positions = JSON.parse(s);
            }catch(e){
              console.error(e);
            }
            if (Object.keys(this.positions).length <= 0) {
              this.positions = this.init_position();
            }
          }
          else {
            this.positions = this.init_position();
          }
          resolve(true);
        }, (e) => { 
          if (e?.header?.stat == 404001) {
          this.init_postion_file().then(s => {
            this.init_position();
            resolve(true);
            return;
          })

        }
        else {

          console.log(e);
            resolve(false); 
        }
        })
    })
  } 
  init_postion_file(): Promise<boolean> {
    return new Promise<boolean>((resolve) => {
      file.create(this.basePath + "/.ispace", "desktopitem_position.json").subscribe((s) => {
        resolve(true);
      }, (e) => {
        console.log(e);
        resolve(false);
      })
  });

  }
  renderingSetInterval: any;
  rendering() {
    // check
    if (this.desktopItems.length <= 0) {
      return;
    }
    if (Object.keys(this.positions).length <= 0) {
      return;
    }

    // step core:
    let waitInitItems: DesktopItemDto[] = [];
    this.desktopItems.forEach((item) => {
      if (this.positions[item.id]) {
        let position = this.positions[item.id];
        // step 1: check position 是否在body范围内,超出则按边缘值修正 
        let bodyHeight = this.body.nativeElement.clientHeight;
        let bodyWidth = this.body.nativeElement.clientWidth;    
        if (position.x < 0 || position.y < 0 || position.x + 100 > bodyWidth || position.y + 100 > bodyHeight) {
           this.initNewPosition(item); 
        }  else {
        item.position = position;
          
        } 
      }
      else {
        waitInitItems.push(item); 
      }
    })

    waitInitItems.forEach((item) => {
      this.initNewPosition(item);
    })
    if(this.renderingSetInterval)
    {
      clearInterval(this.renderingSetInterval);
      this.renderingSetInterval = null;
    }
     this.renderingSetInterval = setInterval(() => { this.update_position(); }, 1000 * 1);
  }
   initNewPosition(item: DesktopItemDto)  {

    // step init:
    let bodyHeight = this.body.nativeElement.clientHeight;
    let itemHeight = 100;
    let itemWidth = 100;
    let indexPosition = { x: 0, y: 0 }; 


    // step 1: 从position (0,0),顺序位置，并校验，不重合则init当前位置
    while (true) {

      // step 1.1: check 重合
      let isOverlap = false;
      for (let i = 0; i < this.desktopItems.length; i++) {
        let s = this.desktopItems[i];
        if(s.position == undefined)
          {
            continue;
          }
 
          // x check
          let isOverlapX = isRangesIntersection(indexPosition.x, indexPosition.x + itemWidth, s.position.x, s.position.x + itemWidth, false);
          // y check
          let isOverlapY = isRangesIntersection(indexPosition.y, indexPosition.y + itemWidth, s.position.y, s.position.y + itemWidth,false);

          isOverlap = isOverlapX! && isOverlapY!;
          if (isOverlap) { 
            break;
          } 
      }
      if (isOverlap) {
        // step : 根据当前项的高度，计算下一个项的位置 
        if (indexPosition.y + itemHeight * 2 > bodyHeight) {
          indexPosition.y = 0;
          indexPosition.x = indexPosition.x + itemWidth;
        }
        else {
          indexPosition.y = indexPosition.y + itemHeight;
        } 
        continue;
      } 
      item.position = indexPosition;
      break;
        
    }

    return
  }

  convertInfo(info: fileInfoBaseDto): DesktopItemDto { 
    let result = new DesktopItemDto();
    result.id = info.id!;
    result.path = this.basePath + "/" + info.name;
    result.name = info.name ?? (info.isDir ? "未命名文件夹" : "未命名文件");
    result.data = info;
    result.type = info.isDir ? "folder" : "file";
    result.iconUrl = info.isDir ? "images/folder.png" : "images/unknow.png";
    return result;
  }

  init_position(): { [key: string]: { x: number; y: number; }; } {
    // check:
    if (this.desktopItems.length <= 0) {
      return this.positions;
    }

    // step: init 获取当前bodydiv的可视高度、宽度
    let bodyHeight = this.body.nativeElement.clientHeight;

    // 单个所占宽高
    let itemHeight = 100;
    let itemWidth = 100;

    // core : 
    let indexPosition = { x: 0, y: 0 };
    this.desktopItems.forEach((item) => {
      this.positions[item.id] = { x: indexPosition.x, y: indexPosition.y };

      // step : 根据当前项的高度，计算下一个项的位置 
      if (indexPosition.y + itemHeight * 2 > bodyHeight) {
        indexPosition.y = 0;
        indexPosition.x = indexPosition.x + itemWidth;
      }
      else {
        indexPosition.y = indexPosition.y + itemHeight;
      }
    })

    return this.positions;
  }
 
createFolder() { 
  let maxIndex = 0;
  this.desktopItems.filter(s => s.type == "folder" && s.name.startsWith("新建文件夹"))
    .forEach(s => {
       let indexStr = s.name.replace("新建文件夹", "").trim();
       let index = Number(indexStr);
       if (index > maxIndex) {
         maxIndex = index;
       }
    });
    maxIndex++;
  let folderName = "新建文件夹" + maxIndex;
 folder.create(this.basePath, folderName).subscribe(s=>{
   this.load();
 }, e=>{
   console.error(e);
 })
}


  onDragEnded(event: CdkDragEnd<any>, item: DesktopItemDto) {
    item.position = event.source.getFreeDragPosition();
  }



  /*** 新建文件 ***/
  createFile_basePath =  this.basePath + "/.ispace/new_decument_template";
  createFile_templates:fileInfoBaseDto[] = [];

  load_templates() {
    if (this.createFile_templates.length > 0) {
       this.createFile_templates = [];
    }
    let query = new QueryDto();
    query.path = this.createFile_basePath;
    folder.children(query).subscribe(s => {
      this.createFile_templates = s.filter(s => !s.isDir);
    })
  }
  
  createFile(template: fileInfoBaseDto) {

    // 名称 和 后缀
    let data = template.name!.split(".");
    let name = data[0]; 
    let ext = data[1];


    let maxIndex = 0;
    this.desktopItems.filter(s => s.type == "file" && s.name.endsWith('.'+ext) && s.name.startsWith(name))
      .forEach(s => { 
         let indexStr = s.name.replace(name!, "").replace('.'+ext, "").trim();
         let index = Number(indexStr);
         if (index > maxIndex) {
           maxIndex = index;
         }
      });
      maxIndex++;
    let createName = name + maxIndex + '.' + ext;  
     file.copy(this.createFile_basePath + "/" + template.name, this.basePath + "/" + createName).subscribe(s=>{
      this.load();
    }, e=>{
      console.error(e);
    })
  }



 // 桌面项-右键菜单




} 
